package com.heking.security.ssl;

import android.content.Context;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.util.List;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * SSL
 *
 * @Author 35574
 * @Date 2021/10/12
 * @Description
 */
public class ZSSLHelper {
    /**
     * 信任的服务器证书管理器
     */
    private TrustManager[] trustManagers;
    private KeyManager[] keyManagers;
    private SSLContext sslContext;

    private ZSSLHelper() {
    }

    private ZSSLHelper(Context context, List<String> assetsCerPaths, String assetsClientKeyPath, String keyPwd) {
        init(context, assetsCerPaths, assetsClientKeyPath, keyPwd);
    }

    public static ZSSLHelper getInstance(Context context, List<String> assetsCerPaths, String clientKeyPath, String keyPwd) {
        return new ZSSLHelper(context, assetsCerPaths, clientKeyPath, keyPwd);
    }

    public static ZSSLHelper getInstance(List<String> cerAbsPaths, String clientKeyAbsPath, String keyPwd) {
        ZSSLHelper zsslHelper = new ZSSLHelper();
        zsslHelper.init(cerAbsPaths,clientKeyAbsPath,keyPwd);
        return zsslHelper;
    }



    /**
     * 获取SSLContext
     *
     * @param context
     * @param assetsCerPaths assets目录下的服务器证书的相对路径
     * @param assetsClientKeyPath  assets目录下的客服端证书的相对路径
     * @param keyPwd         客服端证书 storepass
     * @return
     */
    public void init(Context context, List<String> assetsCerPaths, String assetsClientKeyPath, String keyPwd) {
        sslContext = null;
        try {
            List<Certificate> certificates = ZCertificateFactory.getInstance(SSLConstants.CERTIFICATE_TYPE_X509)
                    .generateCertificates(context, assetsCerPaths);
            trustManagers = ZTrustManagerFactory.getTrustManagers(null, certificates);
            try {
                keyManagers = ZKeyManagerFactory.getKeyManagers(context, assetsClientKeyPath, keyPwd);
            } catch (Exception e) {
                e.printStackTrace();
            }
            sslContext = SSLContext.getInstance(SSLConstants.SSL_PROTOCOL_TLS);
            sslContext.init(keyManagers, trustManagers, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取SSLContext
     *
     * @param cerAbsPaths 服务器证书的绝对路径
     * @param clientAbsKeyPath  客服端证书的绝对路径
     * @param keyPwd         客服端证书 storepass
     * @return
     */
    public void init(List<String> cerAbsPaths, String clientAbsKeyPath, String keyPwd) {
        sslContext = null;
        try {
            ZCertificateFactory certificateFactory = ZCertificateFactory.getInstance(SSLConstants.CERTIFICATE_TYPE_X509);
            List<Certificate> certificates = certificateFactory.generateCertificates(cerAbsPaths);
            trustManagers = ZTrustManagerFactory.getTrustManagers(null, certificates);
            try {
                keyManagers = ZKeyManagerFactory.getKeyManagers(clientAbsKeyPath, keyPwd);
            } catch (Exception e) {
                e.printStackTrace();
            }
            sslContext = SSLContext.getInstance(SSLConstants.SSL_PROTOCOL_TLS);
            sslContext.init(keyManagers, trustManagers, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public TrustManager[] getTrustManagers() {
        return trustManagers;
    }

    public KeyManager[] getKeyManagers() {
        return keyManagers;
    }

    public SSLContext getSslContext() {
        return sslContext;
    }

    public X509TrustManager getX509TrustManager() {
        X509TrustManager x509TrustManager = null;
        if (trustManagers != null && trustManagers.length > 0) {
            for (TrustManager trustManager : trustManagers) {
                if (trustManager instanceof X509TrustManager) {
                    x509TrustManager = (X509TrustManager) trustManager;
                    break;
                }
            }
        }
        return x509TrustManager;
    }


    /**
     * 获取信任所有证书的SSLContext实例
     *
     * @return
     */
    public static SSLContext getTrustAllSSLContext() {
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance(SSLConstants.SSL_PROTOCOL_TLS);
            //将随机数等加密之后传给服务端。
            sslContext.init(null, new TrustManager[]{new TrustAllX509TrustManager()}, new SecureRandom());
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        return sslContext;
    }


}
